/*
 * nute.h
 *
 *  Created on: 06.05.2012
 *      Author: kreyl
 */

#ifndef NUTE_H_
#define NUTE_H_

#include "stdint.h"
#include "kl_lib.h"
#include "cc1101_rf_settings.h"

// Power levels
#define LOWEST_PWR_LVL_ID   plN30dBm
#define HIGHEST_PWR_LVL_ID  plP5dBm
//#define HIGHEST_PWR_LVL_ID  plN6dBm
#define DESIRED_RSSI        (-90)       // dBm

// ==== Timings ====
#ifdef NUTE_MODE_TIXE
#define RECALIBRATE_DELAY   7002    // ms; recalibrate if no packet received within this time
#endif

#ifdef CC_BITRATE_10K
// Pkt duration is 45 ms
#define REPLY_WAITTIME  108  // ms; delay between start of transmission and end of answer reception, = 2x PktDuration
#elif defined CC_BITRATE_38K4
// Pkt duration is 15 ms
#define REPLY_WAITTIME  33  // ms; delay between start of transmission and end of answer reception, = 2x PktDuration
#elif defined CC_BITRATE_250K
// Pkt duration is 4 ms
#define REPLY_WAITTIME  11  // ms; delay between start of transmission and end of answer reception, = 2x PktDuration
#endif

// ==== Tixe & situation ====
#define TIXE_ADDR_OFFSET    72  // Tixe address is i+offset, where i is hardware address or number in array
#define STATE_CMD_NOCHANGE  0
#define STATE_CMD_BOOM      1
#define STATE_CMD_DELAY     2
#define STATE_CMD_BE_OK     3

#define NOTHING_WAS_ASKED   0
#define SITUATION_WAS_ASKED 1
#define INFO_WAS_ASKED      2
#define RESERVED_WAS_ASKED  3


const char PetName33Buf[] = "Tuzik";
const char PetSex33Buf[] = "M";
const char PetKeeperName33Buf[] = "K.Blinov";
const char PetAge33Buf[] = "2";

const char PetName41Buf[] = "Naida";
const char PetSex41Buf[] = "F";
const char PetKeeperName41Buf[] = "I.Ivanov";
const char PetAge41Buf[] = "3";


struct Situation_t { // 1 byte + 2 + 1*3 + 1*2 + 2 + 4*2 = 18 bytes
    uint8_t State;                  // State of Tixe
    uint16_t Battery;
    Time_t Time;                    // GPS time
    uint8_t IsFixed, SatCount;      // GPS fix and sattelite count
    uint16_t Precision;             // GPS precision
    int32_t Latitude, Longitude;    // GPS coordinates
} PACKED;

struct Info_t { // 4 bytes + 4 + 4 + 4 + 2 = 18 bytes
    uint8_t Restriction[18];
//    uint32_t PetName;               // Pet Name
//    uint32_t Sex;                   // Male of Pet
//    uint32_t PetKeeper;             // Name of Pet Keeper
//    uint32_t Age;                   // Pet Age
//    uint16_t InfoCrc;               // Summ of info
} PACKED;
#ifdef NUTE_MODE_STATION
struct Tixe_t {
    uint32_t Timer;
    bool IsOnline, IsToBeFound;                                     // State of Tixe
    bool tcInfoWasAsked, firstCmd;
    uint8_t Cmd2Ask;
    uint8_t PwrID;
    uint8_t StateCmd;
    uint8_t TypeCmd;
    Situation_t Situation;
    Info_t Info;
};
#define TIXE_COUNT  54
extern Tixe_t Tixe[TIXE_COUNT];
#endif

// ==== Main class of protocol ====
enum RadioTask_t {rtDoTx, rtDoRx};
enum NuteState_t {nsIdle, nsSearch, nsPing, nsWaitingRx, nsTransmitting};
enum TypeCommand_t {tcSituation = 1, tcInfo = 2};

// ==== Packet ====
struct Pkt_t {
    uint8_t AddrTo;
    uint8_t AddrFrom;
    uint8_t PwrID;
    uint8_t TypeCmd;
    union { // size = 19
        struct {
            uint8_t StateCmd;
            uint8_t Arr[18];
        };
        Situation_t Situation;
        Info_t Info;
    };
    uint8_t RSSI;
    uint8_t LQI;
} PACKED;
#define CC_PKT_LEN  (sizeof(Pkt_t)-2)


class Nute_t {
private:
    uint8_t Ccounter, cmd2ask;
    uint32_t ITimer;
#ifdef NUTE_MODE_STATION
    RadioTask_t IRadioTask;
    uint32_t ITixeNumber;
    void DoSearch(void);
    void DoPing(void);
    bool CorrectCrc(Info_t *PInfo);
#endif
    void AdjustPwr(uint8_t *PPwrID);
public:
    NuteState_t State;
    Pkt_t RX_Pkt, TX_Pkt;
    void Init(uint8_t ASelfAddr);
    void Task(void);
    uint8_t ChooseCmd(uint32_t ASelfAddr);
    void HandleNewPkt(void);
    void HandleTxEnd(void);
    void HandleTixeReply(uint32_t AIndx);  // Call this when answer received
#ifdef NUTE_MODE_STATION
    void Ping(uint32_t ATixeNumber, uint8_t TypeOfCmd);
    void Search(uint32_t ATixeNumber);
#endif
};

extern Nute_t Nute;

#endif /* NUTE_H_ */
